package com.eureka.bclass.util;

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
// 1.4.4 版本
import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_core.IplImage;
// 1.4.4 版本以后
//import org.bytedeco.opencv.global.opencv_core;
//import org.bytedeco.opencv.opencv_core.IplImage;

import java.awt.image.BufferedImage;
import java.io.*;

/**
 * @Description:
 * @Author: lixing
 * @Date: 2021/6/18 16:31
 */
public class VideoUtil {
    public static void main(String[] args) throws Exception {
        //System.out.println(System.getProperty("java.library.path"));
        // fetchFrame("C:\\Users\\lixing\\Desktop\\46.mp4", "C:\\Users\\lixing\\Desktop\\sls.png");
        // fetchFrame("https://etiger.oss-cn-hangzhou.aliyuncs.com/etiger/pTbztiHFt4Nb4ZjmGBQXN8J4eehTEPxt.mp4", "png");
    }

//    /**
//     * @Description 获取视频的信息（编码、大小、宽、高等等） 依赖：xuggle-xuggler-5.4
//     * @Author lixing
//     * @Date 2021/7/5 14:14
//     * @Param [videofile]
//     * @return java.util.Map<java.lang.String,java.lang.String>
//     */
//    public static Map<String,String> getInfo(InputStream inputStream) {
//        String filename = "C:\\Users\\lixing\\Desktop\\video.mp4";
//        // first we create a Xuggler container object
//        IContainer container = IContainer.make();
//
//        // we attempt to open up the container
//        int result = container.open(filename, IContainer.Type.READ, null);
//
//        // check if the operation was successful
//        if (result<0) {
//            throw new RuntimeException("Failed to open media file");
//        }
//
//        // query how many streams the call to open found
//        int numStreams = container.getNumStreams();
//
//        // query for the total duration
//        long duration = container.getDuration();
//
//        // query for the file size
//        long fileSize = container.getFileSize();
//
//        // query for the bit rate
//        long bitRate = container.getBitRate();
//
//        System.out.println("Number of streams: " + numStreams);
//        System.out.println("Duration (ms): " + duration);
//        System.out.println("File Size (bytes): " + fileSize);
//        System.out.println("Bit Rate: " + bitRate);
//
//        // iterate through the streams to print their meta data
//        for (int i=0; i<numStreams; i++) {
//
//            // find the stream object
//            IStream stream = container.getStream(i);
//
//            // get the pre-configured decoder that can decode this stream;
//            IStreamCoder coder = stream.getStreamCoder();
//            System.out.println("*** Start of Stream Info ***");
//            System.out.printf("stream %d: ", i);
//            System.out.printf("type: %s; ", coder.getCodecType());
//            System.out.printf("codec: %s; ", coder.getCodecID());
//            System.out.printf("duration: %s; ", stream.getDuration());
//            System.out.printf("start time: %s; ", container.getStartTime());
//            System.out.printf("timebase: %d/%d; ", stream.getTimeBase().getNumerator(), stream.getTimeBase().getDenominator());
//            System.out.printf("coder tb: %d/%d; ", coder.getTimeBase().getNumerator(), coder.getTimeBase().getDenominator());
//            System.out.println();
//
//            if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO) {
//                System.out.printf("sample rate: %d; ", coder.getSampleRate());
//                System.out.printf("channels: %d; ", coder.getChannels());
//                System.out.printf("format: %s", coder.getSampleFormat());
//            } else if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) {
//                System.out.printf("width: %d; ", coder.getWidth());
//                System.out.printf("height: %d; ", coder.getHeight());
//                System.out.printf("format: %s; ", coder.getPixelType());
//                System.out.printf("frame-rate: %5.2f; ", coder.getFrameRate().getDouble());
//            }
//            System.out.println();
//            System.out.println("*** End of Stream Info ***");
//        }
//        return null;
//    }

    /**
     * @Description 获取指定视频的帧并保存为字节输入流
     * @Author lixing
     * @Date 2021/7/5 16:18
     * @Param [videofile 图片网络地址, imgType 图片格式]
     * @return java.io.InputStream
     */
    public static InputStream fetchFrame(String videofile, String imgType) throws Exception, IOException {
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile);
        ff.start();
        ff.getAudioChannels();
        //视频的旋转角度
        String rotate = ff.getVideoMetadata("rotate");
        int lenght = ff.getLengthInFrames();
        int i = 0;
        Frame f = null;
        InputStream inputStream = null;
        while (i < lenght) {
            // 过滤前5帧，避免出现全黑的图片，依自己情况而定
            f = ff.grabFrame();
            if ((i > 5) && (f.image != null)) {
                IplImage src = null;
                if (null != rotate && rotate.length() > 1) {
                    OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
                    src = converter.convert(f);
                    f = converter.convert(rotate(src, Integer.parseInt(rotate)));
                }
                inputStream = doExecuteFrame(f, imgType);
                break;
            }
            i++;
        }
        return inputStream;
    }

    public static IplImage rotate(IplImage src, int angle) {
        IplImage img = IplImage.create(src.height(), src.width(), src.depth(), src.nChannels());
        opencv_core.cvTranspose(src, img);
        opencv_core.cvFlip(img, img, angle);
        return img;
    }

    public static InputStream doExecuteFrame(Frame f, String imgType) {
        if (null == f || null == f.image) {
            return null;
        }
        Java2DFrameConverter converter = new Java2DFrameConverter();
        // 图片对象
        BufferedImage bufferedImage = converter.getBufferedImage(f);
        // 字节输入流
        InputStream inputStream = ImageUtil.getInputStreamFromBufferedImage(bufferedImage, imgType);
        return inputStream;
    }

}
